/* Copyright (c) 2007  Peter Palotas
 *  
 *  This software is provided 'as-is', without any express or implied
 *  warranty. In no event will the authors be held liable for any damages
 *  arising from the use of this software.
 *  
 *  Permission is granted to anyone to use this software for any purpose,
 *  including commercial applications, and to alter it and redistribute it
 *  freely, subject to the following restrictions:
 *  
 *      1. The origin of this software must not be misrepresented; you must not
 *      claim that you wrote the original software. If you use this software
 *      in a product, an acknowledgment in the product documentation would be
 *      appreciated but is not required.
 *  
 *      2. Altered source versions must be plainly marked as such, and must not be
 *      misrepresented as being the original software.
 *  
 *      3. This notice may not be removed or altered from any source
 *      distribution.
 *  
 *  
 *  $Id: ErrorInfo.cs 19 2007-08-15 13:14:32Z palotas $
 */
using System;
using System.Collections.Generic;
using System.Text;

namespace Plossum.CommandLine
{
    /// <summary>
    /// Represents an error generated by the <see cref="CommandLineParser"/>
    /// </summary>
    public class ErrorInfo
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ErrorInfo"/> class.
        /// </summary>
        /// <param name="errorCode">The error code.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <param name="optionName">Name of the option.</param>
        /// <param name="fileName">Name of the file, or null if no file name was available.</param>
        /// <param name="line">The line number on which the error occured, or null if no line information was available.</param>
        internal ErrorInfo(ParseErrorCodes errorCode, string errorMessage, string optionName, string fileName, int? line)
        {
            mErrorCode = errorCode;
            mMessage = errorMessage;
            mOptionName = optionName;
            mLine = line;
            mFileName = fileName;
        }

        #endregion

        #region Public properties

        /// <summary>
        /// Gets or sets the message.
        /// </summary>
        /// <value>The message.</value>
        public string Message
        {
            get { return mMessage; }
            set { mMessage = value; }
        }

        /// <summary>
        /// Gets or sets the error code.
        /// </summary>
        /// <value>The error code.</value>
        public ParseErrorCodes ErrorCode
        {
            get { return mErrorCode; }
            set { mErrorCode = value; }
        }

        /// <summary>
        /// Gets a value indicating whether this error originates from a file, meaning that a file name will be available.
        /// </summary>
        /// <value><c>true</c> if this error originates from a file; otherwise, <c>false</c>.</value>
        public bool OriginatesFromFile
        {
            get { return mFileName != null; }
        }

        /// <summary>
        /// Gets or sets the name of the option causing this error.
        /// </summary>
        /// <value>The name of the option causing this error, or null if no option name is available.</value>
        public string OptionName
        {
            get { return mOptionName; }
            set { mOptionName = value; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance has option name set.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance has option name set; otherwise, <c>false</c>.
        /// </value>
        public bool HasOptionName
        {
            get { return mOptionName != null; }
        }

        /// <summary>
        /// Gets or sets the line on which the error occured.
        /// </summary>
        /// <value>The line on which the error occured, or null if no such information is available.</value>
        public int? Line
        {
            get { return mLine; }
            set { mLine = value; }
        }

        /// <summary>
        /// Gets or sets the name of the file.
        /// </summary>
        /// <value>The name of the file in which the error occured, or null if no file name is available.</value>
        public string FileName
        {
            get { return mFileName; }
            set { mFileName = value; }
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            ErrorInfo error = obj as ErrorInfo;

            if (error == null)
                return false;

            return mErrorCode.Equals(error.mErrorCode) && mMessage.Equals(error.mMessage) &&
                (mOptionName == null ? error.mOptionName == null : mOptionName.Equals(error.mOptionName));
        }

        /// <summary>
        /// Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"></see> is suitable for use in hashing algorithms and data structures like a hash table.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"></see>.
        /// </returns>
        public override int GetHashCode()
        {
            return mMessage.GetHashCode() ^ mErrorCode.GetHashCode() ^ (mOptionName == null ? 0 : mOptionName.GetHashCode());
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </returns>
        public override string ToString()
        {
            StringBuilder str = new StringBuilder();
            str.Append("Error");

            if (mFileName != null)
            {
                str.Append(" in file \"");
                str.Append(mFileName);
                str.Append("\"");
            }

            if (mLine.HasValue)
            {
                str.Append(" on line ");
                str.Append(mLine.Value);
            }
            str.Append(": ");
            str.Append(mMessage);
            return str.ToString(); ;
        }

        #endregion

        #region Private fields

        private string mFileName;
        private ParseErrorCodes mErrorCode;
        private int? mLine;
        private string mMessage;
        private string mOptionName;

        #endregion
    }
}
